package com.foreveross.crawl.adapter.sub.impl20140402.v3;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EntityUtils;
import org.dayatang.excel.ExcelException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.crawl.adapter.AbstractAdapter;
import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.common.exception.self.PageErrorResultException;
import com.foreveross.crawl.common.util.DateUtil;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.domain.airfreight.AbstractPlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.DoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.single.SinglePlaneInfoEntity;
import com.foreveross.crawl.exception.FlightInfoNotFoundException;
import com.foreveross.crawl.exception.NoTicketException;
import com.foreveross.taskservice.common.bean.TaskModel;
import com.google.common.collect.Lists;

/** * http://www.donghaiair.com/ 东海航空适配器
 * 
 * @author gan
 */
public class DongHaiAirAdapter extends AbstractAdapter {

	Logger log = LoggerFactory.getLogger(DongHaiAirAdapter.class);

	public DongHaiAirAdapter(TaskModel taskQueue) {
		super(taskQueue);
	}

	// 头等舱 公务舱 超值头等舱 经济舱map
	private final static Map<String, String> airRoomMap = new HashMap<String, String>();
	static {
		airRoomMap.put("room1", "头等舱");
		airRoomMap.put("room2", "超值头等舱");
		airRoomMap.put("room3", "超值头等舱");
		airRoomMap.put("room4", "经济舱");
	}

	/**
	 * 国内单程,往返
	 */
	public List<Object> paraseToVoS(Object fetchObject) throws Exception {
		String tempResult = fetchObject.toString().trim();
		List<Object> list;
		list = parseSourceDI(new Source(tempResult));

		tempResult = null;
		return list;

	}

	@Override
	public List<Object> paraseToVo(Object obj) throws Exception {
		switch (super.getRouteType()) {
		case INTERNATIONAL_ROUND:
			return null;// 国际往返
		case INTERNATIONAL_ONEWAY:
			return null;// 国际单程
		case DOMESTIC_ONEWAYTRIP:
			return paraseToVoS(obj);// 国内单程
		case DOMESTIC_ROUNDTRIP:
			return paraseToVoS(obj);// 国内往返
		}
		return null;
	}

	private Double getTaxFee(String source) {
		Double tax = null;
		try {
			List<String> taxstr = RegHtmlUtil.regStrs(source, "AllPrice\"><span>.*?￥(.*?)\\s*?</span><span>.*?￥(.*?)\\s*?</span>");
			tax = Double.parseDouble(taxstr.get(1)) + Double.parseDouble(taxstr.get(2));
		} catch (Exception e) {
			tax = null;
		}
		return tax;
	}

	/**
	 * 东海——国内单程,往返
	 */
	private List<Object> parseSourceDI(Source sources) throws Exception {
		List<AbstractPlaneInfoEntity> dataList = Lists.newArrayList();
		SinglePlaneInfoEntity sigPI = null;
		List<CabinEntity> cabinSet = Lists.newArrayList();// 全程舱位
		List<ReturnCabinEntity> returnCabins = Lists.newArrayList();// 回程舱位
		DoublePlaneInfoEntity doublePI = null;
		ReturnDoublePlaneInfoEntity returnPI = null;
		if(sources.toString().contains("没有可用的航班或座位已满")){
			throw new NoTicketException("没有票了");
		}
		List<DoublePlaneInfoEntity> goPlaneInfos = Lists.newArrayList();
		List<ReturnDoublePlaneInfoEntity> returnPlanInfos = Lists.newArrayList(); // 返程信息总和

		List<Element> formList = sources.getAllElements("form");
		if (formList.size() == 0) {
			throw new FlightInfoNotFoundException("没有此航班信息");
		}
		if(formList.size()<2){
			throw new ExcelException("此航班信息抓取有误!");
		}
		Element source = formList.get(1);// 第二个form才需要抓取的数据

		Double taxfee = getTaxFee(source.getContent().toString()); // 抓取税费
		if (taskQueue.getIsReturn() == 1 && taxfee != null) taxfee = taxfee / 2; // 如果为来回程拿到的税费为来回和总计，所以分开两份
		
		List<Element> liList = source.getAllElements("li");
		String flightNo = "", flightStartStr = "", flightEndStr = "";
		if (liList.size() > 0) {
			for (int allLi = 0; allLi < liList.size(); allLi++) {// 一个<li>表示单程，两个表示往返
				String currentHtml = liList.get(allLi).getContent().toString();

				// 1航班号 2开始时间 3结束时间
				String regflightinfo = "<td\\s*?class=\"num\">\\s*?(\\w*?)\\s*?</td>\\s*?<td class=\"date\">(\\d{1,2}:\\d{1,2})<br />\\s*?(\\d{1,2}:\\d{1,2})</td>";
				// 1舱位类型 2舱位价格
				String regcabininfo = "class=\"w\".*?<span.*?>\\s*?<input\\s*?type=\"radio\".*?name=\".*?FlightInfo\".*?value=\".*?/(\\w)_0\"\\s*?/>\\s*?￥(.*?)</span>";

				List<String> flightinfo = RegHtmlUtil.regStrs(currentHtml, regflightinfo);
				List<List<String>> cabininfoss = RegHtmlUtil.retrieveLinkss(currentHtml, regcabininfo);

				flightNo = flightinfo.get(1);
				flightStartStr = flightinfo.get(2);
				flightEndStr = flightinfo.get(3); 
				
				log.info(String.format("正在组装航班：[%s]", flightNo));
				if (taskQueue.getIsReturn() == 0 && allLi == 0) {// 单程
					sigPI = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "DZ", "东海航空", "东海航空公司", flightStartStr, flightEndStr, flightNo, null, null, null, null, null, null, null, null, SinglePlaneInfoEntity.class);
				} else if (allLi == 0 && taskQueue.getIsReturn() == 1) {// 返往，去程
					doublePI = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "DZ", "东海航空", "东海航空公司", flightStartStr, flightEndStr, flightNo, null, null, null, null, null, null, null, null, DoublePlaneInfoEntity.class);
				} else if (allLi == 1 && taskQueue.getIsReturn() == 1) {// 返往，回程
					returnPI = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "DZ", "东海航空", "东海航空公司", flightStartStr, flightEndStr, flightNo, null, null, null, null, null, null, null, null, ReturnDoublePlaneInfoEntity.class);
				}

				log.info(String.format("正在组装航班：[%s]的舱位信息，Size:%s", flightNo,cabininfoss.size()));
				for (int cabinindex = 0; cabinindex < cabininfoss.size(); cabinindex++) {
					List<String> cabininfos = cabininfoss.get(cabinindex);
					if (allLi == 0) {
						CabinEntity cabinEn = PlaneInfoEntityBuilder.buildCabinInfo(null, cabininfos.get(1), null, taxfee + "", cabininfos.get(2), null, null, null, CabinEntity.class);
						cabinSet.add(cabinEn);
					} else if (allLi == 1) {
						ReturnCabinEntity recabinEn = PlaneInfoEntityBuilder.buildCabinInfo(null, cabininfos.get(1), null, taxfee + "", cabininfos.get(2), null, null, null, ReturnCabinEntity.class);
						returnCabins.add(recabinEn);
					}
				}
			}

			if (taskQueue.getIsReturn() == 0) {// 单程
				if (cabinSet.size() > 0) {// 舱位
					sigPI.getCabins().addAll(cabinSet);
				}
				dataList.add(sigPI);
			} else if (taskQueue.getIsReturn() == 1) {
				if (returnCabins.size() > 0) {
					returnPI.getReturnCabins().addAll(returnCabins);// 存入回程舱位
				}
				doublePI.getCabins().addAll(cabinSet);
				goPlaneInfos.add(doublePI);
				returnPlanInfos.add(returnPI);
				PlaneInfoEntityBuilder.buildRelation(goPlaneInfos, returnPlanInfos);
				returnPlanInfos.add(returnPI);
				doublePI.getReturnPlaneInfos().addAll(returnPlanInfos);
				dataList.add(doublePI);
			}

		}
		PlaneInfoEntityBuilder.buildLimitPrice(dataList);
		Object obj = dataList;
		
		rollbackProxyIp(true);
		return (List<Object>) obj;

	}

	/**
	 * 国内单程URL，往返ＵＲＬ
	 */
	@Override
	public String getUrl() throws Exception {
		String url = "http://b2c.donghaiair.com/dz/FlightSearch.do?";
		String tripType = "";
		if (taskQueue.getReturnGrabDate() != null && taskQueue.getIsReturn() == 1) {
			tripType = "RT";
		} else {
			tripType = "OW";
		}
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		String tdate = df.format(new Date());
		int dt = DateUtil.compare_date(taskQueue.getFlightDate(), tdate);
		int dr = 0;

		try {
			String takeoffdate = "";
			String returndate = "";

			if (taskQueue.getIsReturn() == 1) {// 往返
				takeoffdate = taskQueue.getFlightDate();
				returndate = taskQueue.getReturnGrabDate();
				dr = DateUtil.compare_date(returndate, tdate);
				if (dr < 0) {
					returndate = tdate;
				}
				if (dt < 0) {
					takeoffdate = tdate;
				}
			}
			if (taskQueue.getIsReturn() == 0) {// 单程
				takeoffdate = taskQueue.getFlightDate();
				dr = DateUtil.compare_date(takeoffdate, tdate);
				if (dt < 0) {
					takeoffdate = tdate;
				}
			}
			String params = "adt=1&chd=0&depDate=" + takeoffdate + "&destCity=" + taskQueue.getToCity() + "&" + "destCityInput=" + URLEncoder.encode(taskQueue.getToCityName(), "gb2312") + "&" + "journeyType=" + tripType + "&orgCity="
					+ taskQueue.getFromCity() + "&" + "orgCityInput=" + URLEncoder.encode(taskQueue.getFromCityName(), "gb2312") + "&" + "retDate=" + returndate;
			url += params;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return url;
	}

	@Override
	public Object fetch(String url) throws Exception {
		switch (super.getRouteType()) {
		case INTERNATIONAL_ROUND:
			return null;// 国际往返
		case INTERNATIONAL_ONEWAY:
			return null;// 国际单程
		case DOMESTIC_ONEWAYTRIP:
			return fetchDomeOneWay();// 国内单程
		case DOMESTIC_ROUNDTRIP:
			return fetchDomeOneWay();// 国内往返
		}
		return null;
	}

	private Object fetchDomeOneWay() throws Exception {
		HttpClient client = null;
		HttpPost httpPost = null;
		HttpResponse response = null;
		HttpEntity entity = null;
		net.htmlparser.jericho.Source source = null;
		try {
			client = super.getHttpClient();
			httpPost = new HttpPost(getUrl());

			httpPost.setHeader("x-requested-with", "XMLHttpRequest");
			httpPost.setHeader("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
			httpPost.setHeader("Referer", "http://b2c.csair.com/B2C40/modules/booking/basic/flightSelectDirect.jsp");
			httpPost.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
			httpPost.setHeader("Accept-Encoding", "gzip, deflate");
			httpPost.setHeader("Host", "b2c.donghaiair.com");

			response = client.execute(httpPost);
			entity = response.getEntity();

			source = new Source(entity.getContent());
			super.appendPageContents(source.getParseText().toString());
			setLenghtCount(super.getSourceWebPageContents().length());

			return source;
		} finally {
			if (httpPost != null) httpPost.releaseConnection();
			client = null;
			httpPost = null;
			if (entity != null) EntityUtils.consume(entity);
			entity = null;
			response = null;
		}

	}

	@Override
	public boolean validateFetch(Object fetchObject) throws Exception {

		if (fetchObject == null) {
			return false;
		} else if (fetchObject instanceof String) {
			if (((String) fetchObject).length() < 500) {
				throw new PageErrorResultException("抓取的数据不正确(长度少于500)");
			}
			String result = RegHtmlUtil.regStr((String) fetchObject, this.getErrors());
			if (result != null) {
				throw new PageErrorResultException(result);
			}
		} else if (StringUtils.isNotBlank(getSourceWebPageContents())) {
			if (getSourceWebPageContents().length() < 500) {
				throw new PageErrorResultException("抓取的数据不正确(长度少于500)");
			}
			String result = RegHtmlUtil.regStr(getSourceWebPageContents(), this.getErrors());
			if (result != null) {
				throw new PageErrorResultException(result);
			}
		}
		return true;
	}

	private List<String> getErrors() {
		List<String> errors = new ArrayList<String>();
		errors.add("404 Not Found");
		errors.add("<title>系统错误提示信息</title>");
		errors.add("<head><title>301 Moved Permanently</title></head>");
		errors.add("<title>502 Proxy Error</title>");
		errors.add("<title>ERROR: The requested URL could not be retrieved</title>");
		return errors;
	}
}
